/*--------------------------------------------------------------------------------------*\
**
** adv_ferry.cpp
**
** Heroes IV
** Copyright 2000, The 3DO Company
**
\*--------------------------------------------------------------------------------------*/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "adventure_events_mover.h"

#include "adventure_map.h"
#include "adventure_map_window.h"
#include "army.h"
#include "bound_handler.h"
#include "game_time.h"
#include "replay_mover.h"

namespace 
{
	const int k_memory_event_buffer_size	= 0;
	const int k_event_lifespan				= 0*1000;			//in mili-seconds
};

t_adventure_event_mover::t_adventure_event_mover ( ) 
: t_adventure_event_base ( k_mover_event ) 
{ 
}

t_adventure_event_mover::t_adventure_event_mover ( t_army* army,  t_adventure_path const & path , bool limit_move, t_adv_map_point orig_point) 
: t_adventure_event_base ( k_mover_event ) 
{ 
	m_global_id		= army->get_global_id();
	
	preprocess_path( path, army->get_position() );

	//the m_path runs to the original position of the amry.

	if (m_path.size() == 0)
	{
		m_is_valid = false;
	}
	else if (m_path.size() >= 1)
	{
		m_begin = orig_point;
		m_end	= m_path[0];
		
		m_end_dir	= army->get_direction();
		m_begin_dir	= m_path[m_path.size()-1].direction;
	}
	
	m_limit_move	= limit_move;
}

void t_adventure_event_mover::cancel_event()
{
	if (m_army_mover != NULL)
		m_army_mover = NULL;
}

void t_adventure_event_mover::execute_event( t_adventure_map* map , t_saved_game_header const & header ) 
{
	//create a replay mover for the object.

	t_adventure_object * object = map->get_adventure_object_with_gid ( m_global_id );
	
	t_army* army = dynamic_cast<t_army*>(object);
	
	if (army == NULL) 
		return;
	
	army->set_path(m_path);
	
	m_army_mover = new t_replay_mover( map->get_map_window(), army, m_path, m_limit_move );
}

void t_adventure_event_mover::undo_event( t_adventure_map* map , t_saved_game_header const & header )
{
	t_adventure_object * object = map->get_adventure_object_with_gid ( m_global_id );
	
	t_army* army = dynamic_cast<t_army*>(object);
	
	if (army == NULL) 
		return;
	
	army->teleport(m_begin);
}

void t_adventure_event_mover::preprocess_path( t_adventure_path const & path, t_level_map_point_2d	army_pos )
{
	//preprocess_path : 
	//	-reverses the order of the path.
	//	-tunrcates the path to the current position of the army
	//to handle on_stop events within the path.

	int size = path.size();
	int truncate_size = size-1;
	int original_size = size;

	for (int i = 0; i < original_size; i ++)
	{
		if (path[i] == army_pos)
		{
			truncate_size = i;
		}
	}

	std::vector<t_adventure_path_point>::const_iterator		path_iter = path.end();
	
	while (size > 0)
	{
		size--;
		path_iter--;

		if (size <= truncate_size)
			m_path.push_back(*path_iter);
	}
}

void t_adventure_event_mover::mover_finish()
{	
	m_army_mover = NULL;
	
	m_time_end = get_time() + k_event_lifespan;
}

void t_adventure_event_mover::update( )
{
	if (m_is_finished) 
		return;

	if (m_army_mover != NULL)
	{
		if (m_army_mover->is_done() == true)
		{
			mover_finish();
		}
	}
	
	if (m_time_end < get_time() && m_army_mover == NULL)
		finished();
}

bool t_adventure_event_mover::read( std::streambuf & buffer , int version )
{
	if (version >= 30)
	{
		buffer >> m_begin;
		buffer >> m_end;
	}
	else
	{
		t_level_map_point_2d	begin;
		t_level_map_point_2d	end;
		
		buffer >> begin;
		buffer >> end;

		(t_level_map_point_2d)m_begin	= begin;
		(t_level_map_point_2d)m_end		= end;
	}
	
	m_begin_dir = get<t_direction> (buffer);
	m_end_dir	= get<t_direction> (buffer);

	if (version >= 42)
		m_path.read( buffer );
	else
		m_path.read( buffer, -1 );

	return t_adventure_event_base::read( buffer , version );
}

bool t_adventure_event_mover::write( std::streambuf & buffer )
{
	buffer << m_begin;
	buffer << m_end;

	put<t_direction> (buffer, m_begin_dir);
	put<t_direction> (buffer, m_end_dir);

	m_path.write(buffer);

	return  t_adventure_event_base::write( buffer );
}
